home *** CD-ROM | disk | FTP | other *** search
- /*
- * FILE
- * createplan
- *
- * DESCRIPTION
- * Routines to create the desired plan for processing a query
- *
- */
-
- /* RcsId("$Header: /private/postgres/src/planner/plan/RCS/createplan.c,v 1.54 1992/07/23 15:13:34 joey Exp $"); */
-
- /*
- * EXPORTS
- * create_plan
- */
-
- #include "tmp/c.h"
-
- #include "nodes/execnodes.h"
- #include "nodes/plannodes.h"
- #include "nodes/plannodes.a.h"
- #include "nodes/relation.h"
- #include "nodes/relation.a.h"
- #include "nodes/primnodes.h"
- #include "nodes/primnodes.a.h"
-
- #include "utils/log.h"
- #include "utils/lsyscache.h"
-
- #include "planner/internal.h"
- #include "planner/clause.h"
- #include "planner/clauseinfo.h"
- #include "planner/clauses.h"
- #include "planner/createplan.h"
- #include "planner/setrefs.h"
- #include "planner/tlist.h"
- #include "planner/planner.h"
- #include "planner/xfunc.h"
-
- #include "lib/lisplist.h"
- #include "lib/lispsort.h"
-
- #define TEMP_SORT 1
- #define TEMP_MATERIAL 2
- /* "Print out the total cost at each query processing operator" */
-
- /* ================
- * GENERIC ROUTINES
- * ================
- */
-
- /*
- * create_plan
- *
- * Creates the access plan for a query by tracing backwards through the
- * desired chain of pathnodes, starting at the node 'best-path'. For
- * every pathnode found:
- * (1) Create a corresponding plan node containing appropriate id,
- * target list, and qualification information.
- * (2) Modify ALL clauses so that attributes are referenced using
- * relative values.
- * (3) Target lists are not modified, but will be in another routine.
- *
- * 'best-path' is the best access path
- *
- * Returns the optimal(?) access plan.
- *
- */
-
- /* .. create_join_node, subplanner */
-
- Plan
- create_plan(best_path)
- Path best_path;
- {
- List tlist;
- Plan plan_node = (Plan)NULL;
- Plan sorted_plan_node = (Plan)NULL;
- Rel parent_rel;
- Count size;
- Count width;
- Count pages;
- Count tuples;
-
- parent_rel = get_parent(best_path);
- tlist = get_actual_tlist(get_targetlist(parent_rel));
- size = get_size(parent_rel);
- width = get_width(parent_rel);
- pages = get_pages(parent_rel);
- tuples = get_tuples(parent_rel);
-
- switch(get_pathtype(best_path)) {
- case T_IndexScan :
- case T_SeqScan :
- plan_node = (Plan)create_scan_node(best_path,tlist);
- break;
- case T_HashJoin :
- case T_MergeJoin :
- case T_NestLoop:
- plan_node = (Plan)create_join_node((JoinPath)best_path, tlist);
- break;
- default: /* do nothing */
- break;
- }
-
- set_plan_size(plan_node, size);
- set_plan_width(plan_node, width);
- if (pages == 0) pages = 1;
- set_plan_tupperpage(plan_node, tuples/pages);
- set_fragment(plan_node, 0);
-
- /* sort clauses by cost/(1-selectivity) -- JMH 2/26/92 */
- if (XfuncMode != XFUNC_OFF)
- {
- set_qpqual((Plan) plan_node,
- lisp_qsort((LispValue) get_qpqual((Plan) plan_node),
- xfunc_clause_compare));
- if (XfuncMode != XFUNC_NOR)
- /* sort the disjuncts within each clause by cost -- JMH 3/4/92 */
- xfunc_disjunct_sort(plan_node->qpqual);
- }
-
- /* Attach a SORT node to the path if a sort path is specified. */
-
- #if 0
- /* this piece of code has been long dead -- Wei */
- if (get_pathsortkey(best_path) &&
- (_query_max_level_ == 1)) {
- set_qptargetlist(plan_node,
- (List)fix_targetlist(origtlist,
- get_qptargetlist(plan_node)));
- sorted_plan_node = (Plan)sort_level_result(plan_node,
- length(get_varkeys(
- get_pathsortkey(best_path))));
- }
- else
- #endif
- if(get_pathsortkey(best_path)) {
- sorted_plan_node = (Plan)make_temp(tlist,
- get_varkeys(get_pathsortkey(best_path)),
- get_sortorder(get_pathsortkey(best_path)),
- plan_node,TEMP_SORT);
-
- }
-
- if(sorted_plan_node) {
- plan_node = sorted_plan_node;
-
- }
-
- return(plan_node);
-
- } /* function end */
-
- /*
- * create_scan_node
- *
- * Create a scan path for the parent relation of 'best-path'.
- *
- * 'tlist' is the targetlist for the base relation scanned by 'best-path'
- *
- * Returns the scan node.
- *
- */
-
- /* .. create_plan */
-
- Scan
- create_scan_node(best_path,tlist)
- Path best_path;
- List tlist ;
- {
- /*Extract the relevant clauses from the parent relation and replace the */
- /* operator OIDs with the corresponding regproc ids. */
-
- /*
- ** CHANGE: now that local predicate clauses are copied into paths
- ** in find_rel_paths() and then (possibly) pulled up in xfunc_trypullup(),
- ** we get the relevant clauses from the path itself, not its parent
- ** relation. --- JMH, 6/15/92
- */
-
- Scan node;
-
- /* Old version (pre 6/15/92)
- ** LispValue scan_clauses = fix_opids(get_actual_clauses
- ** (get_clauseinfo
- ** (get_parent
- ** (best_path))));
- */
- /* New version (6/15/92) */
- LispValue scan_clauses = fix_opids(get_actual_clauses
- (get_locclauseinfo(best_path)));
-
- switch(get_pathtype(best_path)) {
-
- case T_SeqScan :
- node = (Scan)create_seqscan_node(best_path,tlist,scan_clauses);
- break;
-
- case T_IndexScan:
- node = (Scan)create_indexscan_node((IndexPath)best_path,
- tlist,scan_clauses);
- break;
-
- default :
- elog(WARN,"create_scan_node: unknown node type",
- get_pathtype(best_path));
- break;
- }
- set_parallel((Plan)node, 1);
- return node;
-
- } /* function end */
-
- /*
- * create_join_node
- *
- * Create a join path for 'best-path' and(recursively) paths for its
- * inner and outer paths.
- *
- * 'tlist' is the targetlist for the join relation corresponding to
- * 'best-path'
- *
- * Returns the join node.
- *
- */
-
- /* .. create_plan */
-
- Join
- create_join_node(best_path,tlist)
- JoinPath best_path;
- List tlist ;
- {
- Plan outer_node;
- LispValue outer_tlist;
- Plan inner_node;
- List inner_tlist;
- LispValue clauses;
- Join retval;
-
- outer_node = create_plan((Path)get_outerjoinpath(best_path));
- outer_tlist = get_qptargetlist(outer_node);
-
- inner_node = create_plan((Path)get_innerjoinpath(best_path));
- inner_tlist = get_qptargetlist(inner_node);
-
- clauses = get_actual_clauses(get_pathclauseinfo(best_path));
-
- switch(get_pathtype((Path)best_path)) {
-
- case T_MergeJoin :
- retval = (Join)create_mergejoin_node((MergePath)best_path,
- tlist,clauses,
- outer_node,outer_tlist,
- inner_node,inner_tlist);
- break;
- case T_HashJoin :
- retval = (Join)create_hashjoin_node((HashPath)best_path,tlist,
- clauses,outer_node,outer_tlist,
- inner_node,inner_tlist);
- break;
- case T_NestLoop :
- retval = (Join)create_nestloop_node((JoinPath)best_path,tlist,
- clauses,outer_node,outer_tlist,
- inner_node,inner_tlist);
- set_parallel(inner_node, 0);
- break;
- default: /* do nothing */
- elog(WARN,"create_join_node: unknown node type",
- get_pathtype((Path)best_path));
- }
-
- /*
- ** Expensive function pullups may have pulled local predicates
- ** into this path node. Put them in the qpqual of the plan node.
- ** -- JMH, 6/15/92
- */
- if (get_locclauseinfo(best_path) != LispNil)
- set_qpqual((Plan)retval,
- nconc(get_qpqual((Plan) retval),
- fix_opids(get_actual_clauses
- (get_locclauseinfo(best_path)))));
-
- set_parallel((Plan)retval, 1);
- return(retval);
-
- } /* function end */
-
- /* ==========================
- * BASE-RELATION SCAN METHODS
- * ==========================
- */
-
- /*
- * create_seqscan_node
- *
- * Returns a seqscan node for the base relation scanned by 'best-path'
- * with restriction clauses 'scan-clauses' and targetlist 'tlist'.
- *
- */
-
- /* .. create_scan_node */
-
- SeqScan
- create_seqscan_node(best_path,tlist,scan_clauses)
- Path best_path;
- List tlist;
- LispValue scan_clauses ;
- {
- SeqScan scan_node = (SeqScan)NULL;
- Index scan_relid = -1;
- LispValue temp;
-
- temp = get_relids(get_parent(best_path));
- if(null(temp))
- elog(WARN,"scanrelid is empty");
- else
- scan_relid = (Index)CInteger(CAR(temp));
- scan_node = make_seqscan(tlist,
- scan_clauses,
- scan_relid,
- (Plan)NULL);
-
- set_cost((Plan)scan_node,get_path_cost(best_path));
-
- return(scan_node);
-
- } /* function end */
-
- /*
- * create_indexscan_node
- *
- * Returns a indexscan node for the base relation scanned by 'best-path'
- * with restriction clauses 'scan-clauses' and targetlist 'tlist'.
- *
- */
-
- /* .. create_scan_node */
-
- IndexScan
- create_indexscan_node(best_path,tlist,scan_clauses)
- IndexPath best_path;
- List tlist;
- List scan_clauses ;
- {
- /* Extract the(first if conjunct, only if disjunct) clause from the */
- /* clauseinfo list. */
- Expr index_clause = (Expr)NULL;
- List indxqual = LispNil;
- List qpqual = LispNil;
- List fixed_indxqual = LispNil;
- IndexScan scan_node = (IndexScan)NULL;
-
- /* If an 'or' clause is to be used with this index, the indxqual */
- /* field will contain a list of the 'or' clause arguments, e.g., the */
- /* clause(OR a b c) will generate: ((a) (b) (c)). Otherwise, the */
- /* indxqual will simply contain one conjunctive qualification: ((a)). */
-
- if(!null(get_indexqual(best_path)))
- /* added call to fix_opids, JMH 6/23/92 */
- index_clause = (Expr)
- CAR(fix_opids
- (get_actual_clauses((LispValue)get_indexqual(best_path))));
-
-
- if(or_clause_p((LispValue)index_clause)) {
- LispValue temp = LispNil;
-
- foreach(temp,get_orclauseargs((LispValue)index_clause))
- indxqual = nappend1(indxqual,lispCons(CAR(temp),LispNil));
- }
- else {
- indxqual = lispCons(get_actual_clauses(get_indexqual(best_path)),
- LispNil);
- }
- /* The qpqual field contains all restrictions except the indxqual. */
-
- if(or_clause((LispValue)index_clause))
- qpqual = set_difference(scan_clauses,
- lispCons((LispValue)index_clause,LispNil));
- else
- qpqual = set_difference(scan_clauses, CAR(indxqual));
-
- /* XXX
- fixed_indxqual = fix_indxqual_references(indxqual,best_path);
- */
- fixed_indxqual = indxqual;
- scan_node = make_indexscan(tlist,
- qpqual,
- CInteger(CAR(get_relids
- (get_parent((Path)best_path)))),
- get_indexid(best_path),
- fixed_indxqual);
-
- set_cost((Plan)scan_node,get_path_cost((Path)best_path));
-
- return(scan_node);
-
- } /* function end */
-
- /* .. create_indexscan_node, fix-indxqual-references */
-
- LispValue
- fix_indxqual_references(clause,index_path)
- LispValue clause;
- Path index_path ;
- {
- LispValue newclause;
- if(IsA(clause,Var) &&
- CInteger(CAR(get_relids(get_parent(index_path)))) ==
- get_varno((Var)clause)) {
- int pos = 0;
- LispValue x = LispNil;
- int varatt = get_varattno((Var)clause);
- foreach(x,get_indexkeys(get_parent(index_path))) {
- int att = CInteger(CAR(x));
- if(varatt == att) {
- break;
- }
- pos++;
- }
- newclause = (LispValue)CopyObject(clause);
- set_varattno((Var)newclause, pos + 1);
- return(newclause);
- }
- else
- if(IsA(clause,Const))
- return(clause);
- else
- if(is_opclause(clause) &&
- is_funcclause((LispValue)get_leftop(clause)) &&
- get_funcisindex((Func)get_function((LispValue)get_leftop(clause)))) {
-
- /* (set_opno(get_op clause)
- * (get_funcisindex(get_function(get_leftop clause))))
- * (make_opclause(replace_opid(get_op clause))
- */
- return(make_opclause((Oper)get_op(clause),
- MakeVar((Index)CInteger(CAR(get_relids
- (get_parent(index_path)))),
- 1, /* func indices have one key */
- get_functype((Func)get_function(clause)),
- LispNil, (Pointer)NULL),
- get_rightop(clause)));
-
- }
- else {
- LispValue type = clause_type(clause);
- LispValue new_subclauses = LispNil;
- LispValue subclause = LispNil;
- LispValue i = LispNil;
-
- foreach(i,clause_subclauses(type,clause)) {
- subclause = CAR(i);
- if(subclause)
- new_subclauses = nappend1(new_subclauses,
- fix_indxqual_references(subclause,
- index_path));
-
-
- }
-
- /* XXX new_subclauses should be a list of the form:
- * ( (var var) (var const) ...) ?
- */
-
- if( consp(new_subclauses) ) {
- /* XXX was apply function */
- LispValue i = LispNil;
- LispValue newclause = LispNil;
- LispValue newclauses = LispNil;
-
- newclause = make_clause(type,new_subclauses);
- return(newclause);
-
- }
- else {
- return(clause);
- }
- }
- } /* function end */
-
-
- /* ============
- * JOIN METHODS
- * ============
- */
-
- /*
- * create_nestloop_node
- *
- * Returns a new nestloop node.
- *
- */
-
- /* .. create_join_node */
-
- NestLoop
- create_nestloop_node(best_path,tlist,clauses,
- outer_node,outer_tlist,inner_node,inner_tlist)
- JoinPath best_path;
- List tlist,clauses;
- Plan outer_node;
- List outer_tlist;
- Plan inner_node;
- List inner_tlist ;
- {
- NestLoop join_node = (NestLoop)NULL;
-
- if( IsA(inner_node,IndexScan)) {
-
- /* An index is being used to reduce the number of tuples scanned in
- * the inner relation.
- * There will never be more than one index used in the inner
- * scan path, so we need only consider the first set of
- * qualifications in indxqual.
- */
-
- List inner_indxqual = CAR(get_indxqual((IndexScan)inner_node));
- List inner_qual = (inner_indxqual == LispNil)? LispNil:CAR(inner_indxqual);
-
- /* If we have in fact found a join index qualification, remove these
- * index clauses from the nestloop's join clauses and reset the
- * inner(index) scan's qualification so that the var nodes refer to
- * the proper outer join relation attributes.
- */
-
- if (!(qual_clause_p(inner_qual))) {
- LispValue new_inner_qual = LispNil;
-
- clauses = set_difference(clauses,inner_indxqual);
- new_inner_qual = index_outerjoin_references(inner_indxqual,
- get_qptargetlist
- (outer_node),
- get_scanrelid
- ((Scan)inner_node));
- set_indxqual((IndexScan)inner_node,lispCons(new_inner_qual,LispNil));
- }
- }
- else if (IsA(inner_node,Join)) {
- inner_node = (Plan)make_temp(inner_tlist, LispNil, LispNil,
- inner_node, TEMP_MATERIAL);
- }
- join_node = make_nestloop(tlist,
- join_references(clauses,
- outer_tlist,
- inner_tlist),
- outer_node,
- inner_node);
-
- set_cost((Plan)join_node,get_path_cost((Path)best_path));
-
- return(join_node);
-
- } /* function end */
-
-
- /*
- * create_mergejoin_node
- *
- * Returns a new mergejoin node.
- *
- */
-
- /* .. create_join_node */
-
-
- MergeJoin
- create_mergejoin_node(best_path,tlist,clauses,
- outer_node,outer_tlist,
- inner_node,inner_tlist)
- MergePath best_path;
- List tlist,clauses;
- Plan outer_node;
- List outer_tlist;
- Plan inner_node;
- List inner_tlist ;
- {
- /* Separate the mergeclauses from the other join qualification
- * clauses and set those clauses to contain references to lower
- * attributes.
- */
-
- LispValue qpqual =
- join_references(set_difference(clauses,
- get_path_mergeclauses(best_path)),
- outer_tlist,
- inner_tlist);
-
- /* Now set the references in the mergeclauses and rearrange them so
- * that the outer variable is always on the left.
- */
-
- LispValue mergeclauses =
- switch_outer(join_references(get_path_mergeclauses(best_path),
- outer_tlist,
- inner_tlist));
- RegProcedure opcode =
- get_opcode(get_join_operator((MergeOrder)get_p_ordering((Path)best_path)));
-
- LispValue outer_order =
- lispCons((LispValue) get_left_operator( (MergeOrder)
- get_p_ordering( (Path) best_path)),
- LispNil);
-
- LispValue inner_order =
- lispCons( (LispValue) get_right_operator( (MergeOrder)
- get_p_ordering( (Path) best_path)),
- LispNil);
-
- MergeJoin join_node;
-
- /* Create explicit sort paths for the outer and inner join paths if
- * necessary. The sort cost was already accounted for in the path.
- */
- if( get_outersortkeys(best_path)) {
- Temp sorted_outer_node = make_temp(outer_tlist,
- get_outersortkeys
- (best_path),
- outer_order,
- outer_node,
- TEMP_SORT);
- set_cost((Plan)sorted_outer_node,get_cost(outer_node));
- outer_node = (Plan)sorted_outer_node;
- }
-
- if( get_innersortkeys(best_path)) {
- Temp sorted_inner_node = make_temp(inner_tlist,
- get_innersortkeys
- (best_path),
- inner_order,
- inner_node,TEMP_SORT);
- set_cost((Plan)sorted_inner_node,get_cost(inner_node));
- inner_node = (Plan)sorted_inner_node;
- }
-
- join_node = make_mergesort(tlist,
- qpqual,
- mergeclauses,
- opcode,
- inner_order,
- outer_order,
- inner_node,
- outer_node);
- set_cost((Plan)join_node,get_path_cost((Path)best_path));
- return(join_node);
-
- } /* function end */
-
- /*
- * switch_outer
- *
- * Given a list of merge clauses, rearranges the elements within the
- * clauses so the outer join variable is on the left and the inner is on
- * the right.
- *
- * Returns the rearranged list ?
- * XXX Shouldn't the operator be commuted?!
- *
- */
-
- /* .. create_hashjoin_node, create_mergejoin_node */
-
- LispValue
- switch_outer(clauses)
- LispValue clauses ;
- {
- LispValue t_list = LispNil;
- LispValue clause = LispNil;
- LispValue temp = LispNil;
- LispValue i = LispNil;
-
- foreach(i,clauses) {
- clause = CAR(i);
- if(var_is_outer(get_rightop(clause))) {
- temp = make_clause((LispValue)get_op(clause),
- lispCons((LispValue)get_rightop(clause),
- lispCons((LispValue)get_leftop(clause),
- LispNil)));
- t_list = nappend1(t_list,temp);
- }
- else
- t_list = nappend1(t_list,clause);
-
- }
- return(t_list);
- } /* function end */
-
- /*
- * create_hashjoin_node XXX HASH
- *
- * Returns a new hashjoin node.
- *
- * XXX hash join ops are totally bogus -- how the hell do we choose
- * these?? at runtime? what about a hash index?
- *
- */
-
- /* .. create_join_node */
-
- HashJoin
- create_hashjoin_node(best_path,tlist,clauses,outer_node,outer_tlist,
- inner_node,inner_tlist)
- HashPath best_path;
- List tlist,clauses;
- Plan outer_node;
- List outer_tlist;
- Plan inner_node;
- List inner_tlist ;
- {
- LispValue qpqual =
- /* Separate the hashclauses from the other join qualification clauses
- * and set those clauses to contain references to lower attributes.
- */
- join_references(set_difference(clauses,
- get_path_hashclauses(best_path)),
- outer_tlist,
- inner_tlist);
- LispValue hashclauses =
- /* Now set the references in the hashclauses and rearrange them so
- * that the outer variable is always on the left.
- */
- switch_outer(join_references(get_path_hashclauses(best_path),
- outer_tlist,
- inner_tlist));
- HashJoin join_node;
- Hash hash_node;
- Var innerhashkey;
-
- innerhashkey = get_rightop(CAR(hashclauses));
-
- hash_node = make_hash(inner_tlist, innerhashkey, inner_node);
- join_node = make_hashjoin(tlist,
- qpqual,
- hashclauses,
- outer_node,
- (Plan)hash_node);
- set_cost((Plan)join_node,get_path_cost((Path)best_path));
- return(join_node);
-
- } /* function end */
-
- /* ===================
- * UTILITIES FOR TEMPS
- * ===================
- */
-
- /*
- * make_temp
- *
- * Create plan nodes to sort or materialize relations into temporaries. The
- * result returned for a sort will look like (SEQSCAN(SORT(plan-node)))
- * or (SEQSCAN(MATERIAL(plan-node)))
- *
- * 'tlist' is the target list of the scan to be sorted or hashed
- * 'keys' is the list of keys which the sort or hash will be done on
- * 'operators' is the operators with which the sort or hash is to be done
- * (a list of operator OIDs)
- * 'plan-node' is the node which yields tuples for the sort
- * 'temptype' indicates which operation(sort or hash) to perform
- *
- */
-
- /* .. create_hashjoin_node, create_mergejoin_node, create_plan */
-
- Temp
- make_temp(tlist,keys,operators,plan_node,temptype)
- List tlist;
- List keys;
- List operators;
- Plan plan_node;
- int temptype ;
- {
- /* Create a new target list for the temporary, with keys set. */
- List temp_tlist = set_temp_tlist_operators(new_unsorted_tlist(tlist),
- keys,
- operators);
- Temp retval;
-
- switch(temptype) {
- case TEMP_SORT :
- retval = (Temp)make_seqscan(tlist,
- LispNil,
- _TEMP_RELATION_ID_,
- (Plan)make_sort(temp_tlist,
- _TEMP_RELATION_ID_,
- plan_node,
- length(keys)));
- break;
-
- case TEMP_MATERIAL :
- retval = (Temp)make_seqscan(tlist,
- LispNil,
- _TEMP_RELATION_ID_,
- (Plan)make_material(temp_tlist,
- _TEMP_RELATION_ID_,
- plan_node,
- length(keys)));
- break;
-
- default:
- elog(WARN,"make_temp: unknown temp type",temptype);
-
- }
- return(retval);
-
- } /* function end */
-
-
- /*
- * set-temp-tlist-operators
- *
- * Sets the key and keyop fields of resdom nodes in a target list.
- *
- * 'tlist' is the target list
- * 'pathkeys' is a list of N keys in the form((key1) (key2)...(keyn)),
- * corresponding to vars in the target list that are to
- * be sorted or hashed
- * 'operators' is the corresponding list of N sort or hash operators
- * 'keyno' is the first key number
- * XXX - keyno ? doesn't exist - jeff
- *
- * Returns the modified target list.
- *
- */
-
- /* .. make_temp */
-
- List
- set_temp_tlist_operators(tlist,pathkeys,operators)
- List tlist;
- List pathkeys;
- List operators ;
- {
- LispValue keys = LispNil;
- List ops = operators;
- int keyno = 1;
- Resdom resdom = (Resdom)NULL ;
- LispValue i = LispNil;
-
- foreach(i,pathkeys) {
- keys = CAR(CAR(i));
- resdom = tlist_member((Var)keys,
- tlist);
- if( resdom) {
-
- /* Order the resdom keys and replace the operator OID for each
- * key with the regproc OID.
- */
- set_reskey(resdom,keyno);
- set_reskeyop(resdom,(OperatorTupleForm)get_opcode((ObjectId)CAR(ops))); /* XXX */
- }
- keyno += 1;
- /*
- ops = CDR(ops);
- */
- }
- return(tlist);
- } /* function end */
-
- SeqScan
- make_seqscan(qptlist,qpqual,scanrelid,lefttree)
- List qptlist;
- List qpqual;
- Index scanrelid;
- Plan lefttree;
- {
- SeqScan node = RMakeSeqScan();
-
- if(!null(lefttree))
- Assert(IsA(lefttree,Plan));
-
- set_cost((Plan)node , 0.0 );
- set_fragment((Plan)node, 0 );
- set_state((Plan)node, (EStatePtr)NULL);
- set_qptargetlist((Plan)node, qptlist);
- set_qpqual((Plan)node , qpqual);
- set_lefttree((Plan)node, (PlanPtr)lefttree);
- set_righttree((Plan)node , (PlanPtr) NULL);
- set_scanrelid((Scan)node , scanrelid);
- set_scanstate((Scan)node, (ScanState)NULL);
-
- return(node);
- }
-
- IndexScan
- make_indexscan(qptlist, qpqual, scanrelid,indxid,indxqual)
- List qptlist,qpqual;
- Index scanrelid;
- List indxid, indxqual;
-
- {
- IndexScan node = RMakeIndexScan();
-
- set_cost((Plan)node , 0.0 );
- set_fragment((Plan)node, 0 );
- set_state((Plan)node, (EStatePtr)NULL);
- set_qptargetlist((Plan)node, qptlist);
- set_qpqual((Plan)node , qpqual);
- set_lefttree((Plan)node,(PlanPtr)NULL);
- set_righttree((Plan)node,(PlanPtr)NULL);
- set_scanrelid((Scan)node,scanrelid);
- set_indxid(node,indxid);
- set_indxqual(node,indxqual);
- set_scanstate((Scan)node, (ScanState)NULL);
-
- return(node);
- }
-
-
- NestLoop
- make_nestloop(qptlist,qpqual,lefttree,righttree)
- List qptlist;
- List qpqual;
- Plan lefttree;
- Plan righttree;
- {
- NestLoop node = RMakeNestLoop();
-
- set_cost((Plan)node , 0.0 );
- set_fragment((Plan)node, 0 );
- set_state((Plan)node, (EStatePtr)NULL);
- set_qptargetlist((Plan)node, qptlist);
- set_qpqual((Plan)node , qpqual);
- set_lefttree((Plan)node, (PlanPtr)lefttree);
- set_righttree((Plan)node , (PlanPtr)righttree);
- set_nlstate((NestLoop)node, (NestLoopState)NULL);
- set_ruleinfo((Join)node, (JoinRuleInfoPtr)NULL);
-
- return(node);
- }
-
- HashJoin
- make_hashjoin(tlist,qpqual,hashclauses,lefttree,righttree)
- LispValue tlist, qpqual,hashclauses;
- Plan righttree,lefttree;
- {
- HashJoin node = RMakeHashJoin();
-
- set_cost((Plan)node , 0.0 );
- set_fragment((Plan)node, 0 );
- set_state((Plan)node, (EStatePtr)NULL);
- set_qpqual((Plan)node,qpqual);
- set_qptargetlist((Plan)node,tlist);
- set_lefttree((Plan)node,(PlanPtr)lefttree);
- set_righttree((Plan)node,(PlanPtr)righttree);
- set_ruleinfo((Join)node, (JoinRuleInfoPtr) NULL);
- set_hashclauses(node,hashclauses);
- set_hashjointable(node, NULL);
- set_hashjointablekey(node, 0);
- set_hashjointablesize(node, 0);
- set_hashdone(node, false);
-
- return(node);
- }
-
- Hash
- make_hash(tlist, hashkey, lefttree)
- LispValue tlist;
- Var hashkey;
- Plan lefttree;
- {
- Hash node = RMakeHash();
-
- set_cost((Plan)node , 0.0 );
- set_fragment((Plan)node, 0 );
- set_parallel((Plan)node, 1);
- set_state((Plan)node, (EStatePtr)NULL);
- set_qpqual((Plan)node,LispNil);
- set_qptargetlist((Plan)node,tlist);
- set_lefttree((Plan)node,(PlanPtr)lefttree);
- set_righttree((Plan)node,(PlanPtr)NULL);
- set_hashkey(node, hashkey);
- set_hashtable(node, NULL);
- set_hashtablekey(node, 0);
- set_hashtablesize(node, 0);
-
- return(node);
- }
-
- MergeJoin
- make_mergesort(tlist, qpqual, mergeclauses, opcode, rightorder, leftorder,
- righttree, lefttree)
- LispValue tlist, qpqual,mergeclauses;
- ObjectId opcode;
- LispValue rightorder, leftorder;
- Plan righttree,lefttree;
- {
- MergeJoin node = RMakeMergeJoin();
-
- set_cost((Plan)node , 0.0 );
- set_fragment((Plan)node, 0 );
- set_state((Plan)node, (EStatePtr)NULL);
- set_qpqual((Plan)node,qpqual);
- set_qptargetlist((Plan)node,tlist);
- set_lefttree((Plan)node,(PlanPtr)lefttree);
- set_righttree((Plan)node,(PlanPtr)righttree);
- set_ruleinfo((Join)node, (JoinRuleInfoPtr) NULL);
- set_mergeclauses(node,mergeclauses);
- set_mergesortop(node,opcode);
- set_mergerightorder(node, rightorder);
- set_mergeleftorder(node, leftorder);
-
- return(node);
-
- }
-
- Sort
- make_sort(tlist,tempid,lefttree, keycount)
- LispValue tlist;
- Count keycount;
- Plan lefttree;
- ObjectId tempid;
- {
- Sort node = RMakeSort();
-
- set_cost((Plan)node , 0.0 );
- set_fragment((Plan)node, 0 );
- set_parallel((Plan)node, 1);
- set_state((Plan)node, (EStatePtr)NULL);
- set_qpqual((Plan)node,LispNil);
- set_qptargetlist((Plan)node,tlist);
- set_lefttree((Plan)node,(PlanPtr)lefttree);
- set_righttree((Plan)node,(PlanPtr)NULL);
- set_tempid((Temp)node,tempid);
- set_keycount((Temp)node,keycount);
-
- return(node);
- }
-
- Material
- make_material(tlist,tempid,lefttree, keycount)
- LispValue tlist;
- Count keycount;
- Plan lefttree;
- ObjectId tempid;
- {
- Material node = RMakeMaterial();
-
- set_cost((Plan)node , 0.0 );
- set_fragment((Plan)node, 0 );
- set_parallel((Plan)node, 1);
- set_state((Plan)node, (EStatePtr)NULL);
- set_qpqual((Plan)node,LispNil);
- set_qptargetlist((Plan)node,tlist);
- set_lefttree((Plan)node,(PlanPtr)lefttree);
- set_righttree((Plan)node,(PlanPtr)NULL);
- set_tempid((Temp)node,tempid);
- set_keycount((Temp)node,keycount);
-
- return(node);
- }
-
- Agg
- make_agg(arglist, aggidnum)
- List arglist;
- ObjectId aggidnum;
- {
- /* arglist is(Resnode((interesting stuff), NULL)) */
- Agg node = RMakeAgg();
- Resdom resdom = (Resdom)CAR(arglist);
- String aggname = NULL;
- LispValue query = LispNil;
- List varnode = LispNil;
- arglist = CADR(arglist);
- aggname = CString(CAR(arglist));
- arglist = CDR(arglist);
- query = CAR(arglist);
- arglist = CDR(arglist);
- varnode = CAR(arglist);
- set_cost((Plan)node, 0.0);
- set_fragment((Plan)node, 0);
- set_parallel((Plan)node, 1);
- set_state((Plan)node, (EStatePtr)NULL);
- set_qpqual((Plan)node, LispNil);
- set_qptargetlist((Plan)node,
- lispCons(MakeList((LispValue)resdom,
- varnode,
- -1),
- LispNil));
- set_lefttree((Plan)node, (PlanPtr)planner(query));
- set_righttree((Plan)node, (PlanPtr)NULL);
- set_tempid((Temp)node, aggidnum);
- set_aggname(node, aggname);
- return(node);
- }
-
- /*
- * A unique node always has a SORT node in the lefttree.
- */
-
- Unique
- make_unique(tlist,lefttree)
- List tlist;
- Plan lefttree;
- {
- Unique node = RMakeUnique();
-
- set_cost((Plan)node , 0.0 );
- set_fragment((Plan)node, 0 );
- set_parallel((Plan)node, 1);
- set_state((Plan)node, (EStatePtr)NULL);
- set_qpqual((Plan)node,LispNil);
- set_qptargetlist((Plan)node,tlist);
- set_lefttree((Plan)node,(PlanPtr)lefttree);
- set_righttree((Plan)node,(PlanPtr)NULL);
- set_tempid((Temp)node,-1);
- set_keycount((Temp)node,0);
-
- return(node);
- }
-
- List
- generate_fjoin(tlist)
- List tlist;
- {
- List tlistP;
- List newTlist = LispNil;
- List fjoinList = LispNil;
- int nIters = 0;
-
- /*
- * Break the target list into elements with Iter nodes,
- * and those without them.
- */
- foreach(tlistP, tlist)
- {
- List tlistElem;
-
- tlistElem = CAR(tlistP);
- if ( IsA(CADR(tlistElem),Iter) )
- {
- nIters++;
- fjoinList = nappend1(fjoinList, tlistElem);
- }
- else
- {
- newTlist = nappend1(newTlist, tlistElem);
- }
- }
-
- /*
- * if we have an Iter node then we need to flatten.
- */
- if (nIters > 0)
- {
- LispValue inner;
- List tempList;
- Fjoin fjoinNode;
- DatumPtr results = (DatumPtr)palloc(nIters*sizeof(Datum));
- BoolPtr alwaysDone = (BoolPtr)palloc(nIters*sizeof(bool));
-
- inner = CAR(fjoinList);
- fjoinList = CDR(fjoinList);
- fjoinNode = (Fjoin)MakeFjoin(false,
- nIters,
- inner,
- results,
- alwaysDone);
- tempList = lispCons((LispValue)fjoinNode, LispNil);
- tempList = nconc(tempList, fjoinList);
- newTlist = nappend1(newTlist, tempList);
- }
- return newTlist;
- }
-